package com.fuint.minio.service;

import com.alibaba.fastjson.JSON;
import com.fuint.minio.minIOConst.BucketConst;
import com.fuint.minio.model.UploadResult;
import com.fuint.minio.util.MinIOUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;

/**
 * @ClassName : MinIOService
 * @Description :
 * @Author : wzq
 * @Date: 2022-01-04 17:28
 */
@Slf4j
@Service
public class MinIOService {

    @Autowired
    private MinIOUtil minIOUtil;
    @Value("${minIO.endpoint}")
    private String endpoint;

    /**
     *判断桶是否存在
     */
    public boolean bucketExists(String bucketName) {
        return minIOUtil.bucketExists(bucketName);
    }
    /**
     * 初始化桶,并开启版本管理设置桶策略
     * @param bucketName 桶名称
     * @param isVersion 是否开起版本控制
     * @param setPolicy  是否设置桶策略，不设置直接访问路径 链接403，需要额外请求获取访问链接
     */
    public void initBucket(String bucketName,boolean isVersion,boolean setPolicy){
        log.debug("初始化桶：bucketName：{}",bucketName);
        try {
            if (minIOUtil.bucketExists(bucketName)) return;

            minIOUtil.makeBucket(bucketName);

            if (isVersion) {
                 minIOUtil.setBucketVersioning(bucketName);
            }
            if (setPolicy) {
                 minIOUtil.setBucketPolicy(bucketName, BucketConst.getPolicy(bucketName));
            }
        }catch (Exception e){
            log.error("创建桶出现异常", e);
        }
    }

    /**
     * 创建一个普通桶
     * @param bucketName  桶名称
     */
    public void initBucket(String bucketName){
        this.initBucket(bucketName, false, false);
    }

    /**
     * 删除桶
     */
    public boolean removeBucket(String bucketName) {
        try {
            return minIOUtil.removeBucket(bucketName);
        } catch (Exception e) {
            log.error("删除桶失败", e);
            return false;
        }
    }

    /**
     * 查找出桶内所有的对象名称
     */
    public List<String> listObjects(String bucket){
        try {
            return minIOUtil.listObjectNames(bucket);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Arrays.asList(ArrayUtils.EMPTY_STRING_ARRAY);
    }

    /**
     * 上传对象 upload
     *
     * 视频格式因为浏览器解析成播放不能直接下载 innerPath 返回格式如下
     *  http://10.130.213.10:9000/minio/download/bucketName/testvideo.mp4?token=
     *  其他文件格式如下，设置桶策略以后可以直接浏览器打开
     *  http://10.130.213.10:9000/bucketName/demo.png
     */
    public UploadResult upload(String path , String bucketName, String objectName ){
        UploadResult result = new UploadResult();
        try {
            String versionId = minIOUtil.upload(path, bucketName, objectName);
            result.setCode("200");
            result.setFileName(objectName);
            result.setGroup(bucketName);
            String innerPath = endpoint+"/"+bucketName+"/"+objectName;
            if (objectName.endsWith(BucketConst.JSON_FILE_SUFFIX)){
                innerPath =  minIOUtil.getVideoUrl(endpoint, bucketName, objectName);
            }
            result.setInnerPath(innerPath);
            result.setVersionId(versionId);
        }catch (Exception e){
            result.setCode("500");
            result.setMessage("上传文件出现异常");
            log.error("minio 上传文件失败", e);
        }
        log.debug("上传文件结束：result：{}", JSON.toJSONString(result));
        return result;
    }
    /**
     * @param file 上传文件
     * @param bucketName 桶名称
     * @param fileName 文件名称
     */
    public UploadResult upload(File file,String bucketName,String fileName){
        UploadResult result = new UploadResult();
        if (null == file || file.length() == 0){
            result.setCode("500");
            result.setMessage("上传文件不能为空");
            return result;
        }
        return this.upload(file.getPath(),bucketName, fileName);
    }
    /**
     * @param file 上传文件
     * @param fileName 文件名称
     * 默认传入 istar-tmp 桶
     */
    public UploadResult upload(File file,String fileName){
        return this.upload(file.getPath(), BucketConst.FUNINT_BUCKET, fileName);
    }
    public UploadResult upload(File file){
        return this.upload2bucket(file, BucketConst.FUNINT_BUCKET);
    }
    /**
     * @param file 上传文件
     * @param bucketName 桶名称
     */
    public UploadResult upload2bucket(File file,String bucketName){
        return this.upload(file, bucketName, file.getName());
    }
    /**
     * 上传对象 put
     */
    public UploadResult putObject(String bucketName , InputStream file, String objectName ){
        UploadResult result = new UploadResult();
        try {
            String versionId = minIOUtil.putObject(bucketName, file, objectName);
            result.setCode("200");
            result.setFileName(objectName);
            result.setGroup(bucketName);
            String innerPath = endpoint+"/"+bucketName+"/"+objectName;
            if (objectName.endsWith(BucketConst.JSON_FILE_SUFFIX)){
                innerPath =  minIOUtil.getVideoUrl(endpoint, bucketName, objectName);
            }
            result.setInnerPath(innerPath);
            result.setVersionId(versionId);
        }catch (Exception e){
            log.error("putObject 出现异常：", e);
            result.setCode("500");
            result.setMessage("上传文件出现异常");
        }
        return result;
    }

    /**
     * copy 文件 如果不传目标桶，默认桶为同一个
     * @param copyBucketName 拷贝到哪个桶
     * @param objectName 文件名称
     * @param sourceBucketName 源桶
     * @param sourceObjectName 源文件名称
     */
    public UploadResult copyObject(String copyBucketName, String objectName,String sourceBucketName, String sourceObjectName){
        UploadResult result = new UploadResult();
        try {
            String versionId = minIOUtil.copyObject(copyBucketName, objectName, sourceBucketName,sourceObjectName);
            result.setCode("200");
            result.setFileName(objectName);
            result.setGroup(copyBucketName);
            String innerPath = endpoint+"/"+copyBucketName+"/"+objectName;
            if (objectName.endsWith(BucketConst.JSON_FILE_SUFFIX)){
                innerPath = endpoint + "/minio/download/" + copyBucketName+"/"+objectName + "?token=";
            }
            result.setInnerPath(innerPath);
            result.setVersionId(versionId);
        }catch (Exception e){
            log.error("copyObject 出现异常：", e);
            result.setCode("500");
            result.setMessage("上传文件出现异常");
        }
        return result;
    }

    /**
     * 从桶内拷贝对象
     * @param objectName 拷贝对象名称
     * @param sourceBucketName 源桶
     * @param sourceObjectName 源对象名称
     */
    public UploadResult copyObject(String objectName,String sourceBucketName, String sourceObjectName){
        return this.copyObject(sourceBucketName,objectName,sourceBucketName,sourceObjectName);
    }

    /**
     * 删除对象
     */
    public void removeObject(String bucketName, String objectName,String versionId) {
        minIOUtil.removeObject(bucketName, objectName, versionId);
    }
    public void removeObject(String bucketName, String objectName) {
         this.removeObject(bucketName, objectName, null);
    }
    /**
     * 下载对象 输出文件
     * @param objectName 文件名称
     * @param filePath 文件路径
     * @param versionId 版本号，不传下载最新版本
     */
    public void downloadObject(String bucketName, String objectName, String versionId,String filePath){
        minIOUtil.downloadObject(bucketName, objectName, versionId, filePath);
    }
    /**
     * 下载对象 输出文件
     * @param file 下载的文件
     * @param versionId 版本号，不传下载最新版本
     */
    public void downloadObject(String bucketName,File file, String versionId){
       this.downloadObject(bucketName, file.getName(), versionId, file.getPath());
    }
    /**
     * 下载对象 输出流
     */
    public InputStream getObject(String bucketName, String objectName, String versionId) {
        return minIOUtil.getObject(bucketName, objectName, versionId);
    }
    /**
     * 判断桶内对象是否存在
     */
    public boolean existInBucket(String bucketName, String objectName, String versionId) {
        return minIOUtil.existInBucket(bucketName, objectName, versionId);
    }

    /**
     * 传进来链接获取桶名称
     * 链接格式  http://10.130.213.10:9000/bucket/jsonName.json
     */
    public String getBucketFromUrl(String url){
        if (StringUtils.isBlank(url)) throw new NullPointerException("链接不能为空");
        String afterLast = StringUtils.substringBeforeLast(url, "/");
        return StringUtils.substringAfterLast(afterLast, "/");
    }
}
